%name vasParser
%define LSP_NEEDED
%define ERROR_BODY = 0
%define LEX_BODY = 0

%header{
#include <iostream>
#include <fstream>
#define DZHDEB
#include "debprintf.h"
#include "vacg.h"
#include "node.hxx"
int yylex();
void yyerror(char*);
extern FlowGraph* programGraph;
%}
%union{
AstNode* node;
FlowGraph* graph;
AstExpression* expr;
AstConstExpr* constExpr;
AstStatement* stmt;
int ival;
double dval;
float fval;
char* name;
}

%token <name> TK_IDENTIFIER%token <ival> TK_CONSTANT%token TK_STRING_LITERAL%token TK_SIZEOF%token TK_PTR_OP%token TK_INC_OP%token TK_DEC_OP%token TK_LEFT_OP%token TK_RIGHT_OP%token TK_LE_OP%token TK_GE_OP%token TK_EQ_OP%token TK_NE_OP%token TK_AND_OP%token TK_OR_OP%token TK_MUL_ASSIGN%token TK_DIV_ASSIGN%token TK_MOD_ASSIGN%token TK_ADD_ASSIGN%token TK_SUB_ASSIGN%token TK_LEFT_ASSIGN%token TK_RIGHT_ASSIGN%token TK_AND_ASSIGN%token TK_XOR_ASSIGN%token TK_OR_ASSIGN%token TK_TYPE_NAME%token TK_TYPEDEF%token TK_EXTERN%token TK_STATIC%token TK_AUTO%token TK_REGISTER%token TK_CHAR%token TK_SHORT%token TK_INT%token TK_LONG%token TK_SIGNED%token TK_UNSIGNED%token TK_FLOAT%token TK_DOUBLE%token TK_CONST%token TK_VOLATILE%token TK_VOID%token TK_STRUCT%token TK_UNION%token TK_ENUM%token TK_ELIPSIS%token TK_RANGE%token TK_CASE%token TK_DEFAULT%token TK_IF%token TK_ELSE%token TK_SWITCH%token TK_WHILE%token TK_DO%token TK_FOR%token TK_GOTO%token TK_CONTINUE%token TK_BREAK%token TK_RETURN%token TK_ELLIPSIS%token TK_FRAME%token TK_OFRAME%token TK_SOBEL%token TK_ROBERT%token TK_PREWITT%token TK_LAPlAS%token TK_FREICHEN

%left '-' '+'
%left '*' '/'
%nonassoc TK_UMINUS

%type <expr> expression filterkernel frame edge_operator
%type <constExpr> constantexpression
%type <graph> program statement_list
%type <stmt> statement
%%
program : statement_list { /*programGraph = $1;*/}
        ;
statement_list:	statement ';' {/* $$= new FlowGraph();*/ $$=curRegion; $$->appandNode($1); }
	|	statement_list statement ';' { $$=$1;$1->appandNode($2);}
	;

statement:	expression '=' expression   { $$= new AstAssginState($1,$3);}
    |   TK_OFRAME '=' expression           { $$= new AstAssginState(oFrame_symblinfo ,$3); debprintf("oframe= expression \n");} 
    |   TK_OFRAME '=' TK_FRAME '*' edge_operator{ $$= new AstFilterState(oFrame_symblinfo , curFrame_symblinfo ,((AstVarExpr*)$5)->var ); debprintf("Oframe=frame*sobel detect(oframe, frame, sobel); \n"); 
    delete $5;
    } 
    ;

expression:	expression '+' expression   { $$= new AstOpExpr(OpCode('+'),$1,$3);debprintf("e+e\n");  }
          |	expression '-' expression   { $$= new AstOpExpr(OpCode('-'),$1,$3); }
    |	expression '*' expression       { $$= new AstOpExpr(OpCode('*'),$1,$3);}
    |	expression '/' expression    	{ $$= new AstOpExpr(OpCode('/'),$1,$3);}
    |	'-' expression %prec TK_UMINUS	    { }
    |	'(' expression ')'			   	{ $$=$2 }
    |   constantexpression              { $$=$1;}
    |	TK_CONSTANT                     { $$= new AstConstExpr($1); }
    |	TK_IDENTIFIER                   { SymbolInfo* var = curRegion-> getornewSymbolInfo($1); $$= new AstVarExpr(*var);}
    |   filterkernel                    {}
    |   frame                           {}  
    |   edge_operator                   {}    
    ;

filterkernel: 
             | TK_FREICHEN                  { $$=new AstVarExpr(FreiChen_symblinfo);debprintf("[%d]",FreiChen);}
            ;

frame:
    |   TK_FRAME                           { $$=new AstVarExpr(curFrame_symblinfo );debprintf("frame[%d]",0);}
    |   TK_FRAME '[' TK_CONSTANT ']'          { $$=new AstVarExpr(nxtFrame_symblinfo );debprintf("frame[%d]",$3); }
    |   TK_FRAME '[' '-' TK_CONSTANT ']'      { $$=new AstVarExpr(preFrame_symblinfo );debprintf("frame[%d]",$4); }
;

edge_operator: TK_SOBEL                     { $$=new AstVarExpr(Sobel_symblinfo   );debprintf("[%d]",Sobel);}
             | TK_ROBERT                    { $$=new AstVarExpr(Robert_symblinfo  );debprintf("[%d]",Robert);}  
             | TK_PREWITT                   { $$=new AstVarExpr(Prewitt_symblinfo );debprintf("[%d]",Prewitt );}
             | TK_LAPlAS                    { $$=new AstVarExpr(LapLas_symblinfo  );debprintf("[%d]",LapLas  );}
;

constantexpression:
                  |   TK_CONSTANT '+' TK_CONSTANT           { printf("+\n");$$ = new AstConstExpr($1 + $3); }
    |	TK_CONSTANT '-' TK_CONSTANT           { $$ = new AstConstExpr($1 - $3); }
    |	TK_CONSTANT '*' TK_CONSTANT           { $$ = new AstConstExpr($1 * $3); }
    |	TK_CONSTANT '/' TK_CONSTANT{	if($3 == 0.0)
                        yyerror("divide by zero");
                    else
                        $$ = new AstConstExpr($1 / $3);
                }

%%
FlowGraph* programGraph=rootRegion;
void yyerror(char* s)
{
}
